﻿#include "CBackendWnd.h"

#include <QButtonGroup>
#include <QStandardItem>
#include <QStandardItemModel>
#include <QDesktopServices>
#include <QUrl>
#include <QHeaderView>
#include <QInputDialog>
#include <QMessageBox>
#include <QTimer>
#include <QProcess>

#include "glog/logging.h"

#include "AppModel.h"
#include "CustomBoxView.h"
#include "CabinetManager.h"
#include "COrderManager.h"
#include "CPaymentManager.h"
#include "custom/CToastBox.h"
#include "CDoorControlBoardEditDlg.h"
#include "CPaymentPlanEditDlg.h"
#include "CSystemSettingsDlg.h"
#include "custom/inputnew/frminputnew.h"

#define DATETIME_CURSTR		(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss").toStdString())
#define ROLE_ORDERSTATUS	Qt::UserRole + 1
#define ROLE_LOCKERNO		Qt::UserRole + 2
#define ROLE_ORDERTYPE		Qt::UserRole + 3

#define ROLE_PAYMENT(INDEX)             (Qt::UserRole + 4 + INDEX)
#define ROLE_PAYMENT_ID                 ROLE_PAYMENT(1)
#define ROLE_PAYMENT_ALIAS              ROLE_PAYMENT(2)
#define ROLE_PAYMENT_ISFREEE            ROLE_PAYMENT(3)
#define ROLE_PAYMENT_PREPAID            ROLE_PAYMENT(4)
#define ROLE_PAYMENT_TRAIL_DURATION     ROLE_PAYMENT(5)
#define ROLE_PAYMENT_BILLING_UNIT       ROLE_PAYMENT(6)
#define ROLE_PAYMENT_BILLING_PERIOD     ROLE_PAYMENT(7)
#define ROLE_PAYMENT_BILLING_PRICE      ROLE_PAYMENT(8)
#define ROLE_PAYMENT_BILLING_CAPS       ROLE_PAYMENT(9)

#define ROLE_DCB(INDEX)                 (Qt::UserRole + 100 + INDEX)
#define ROLE_DCB_PROTOCOL               ROLE_DCB(0)
#define ROLE_DCB_TYPE                   ROLE_DCB(1)
#define ROLE_DCB_ISSHARED               ROLE_DCB(2)
#define ROLE_DCB_LOCALPORT              ROLE_DCB(3)
#define ROLE_DCB_REMOTEADDR             ROLE_DCB(4)
#define ROLE_DCB_REMOTEPORT             ROLE_DCB(5)
#define ROLE_DCB_COM                    ROLE_DCB(6)
#define ROLE_DCB_BAUDRATE               ROLE_DCB(7)
#define ROLE_DCB_FLOW_CONTROL           ROLE_DCB(8)
#define ROLE_DCB_PARITY                 ROLE_DCB(9)
#define ROLE_DCB_STOPBITS               ROLE_DCB(10)
#define ROLE_DCB_CHARACTERSIZE          ROLE_DCB(11)
#define ROLE_DCB_TIMEOUTCONN            ROLE_DCB(12)
#define ROLE_DCB_TIMEOUTREAD            ROLE_DCB(13)
#define ROLE_DCB_TIMEOUTWRITE           ROLE_DCB(14)
#define ROLE_DCB_COL                    ROLE_DCB(15)
#define ROLE_DCB_COUNT                  ROLE_DCB(16)
#define ROLE_DCB_INDEX                  ROLE_DCB(17)
#define ROLE_DCB_FLAG                   ROLE_DCB(99)

using namespace zl;

CBackendWnd::CBackendWnd(QWidget *parent)
	: QWidget(parent)
    , model_layout_(new QStandardItemModel)
    , model_dcb_(new QStandardItemModel)
	, model_manager_card_(new QStandardItemModel)
    , model_query_(new QStandardItemModel)
    , model_payment_(new QStandardItemModel)
	, wnd_layout_(new CCustomBoxView)
	, timer_(new QTimer(this))
{
	ui.setupUi(this);
	init();
    setAttribute(Qt::WA_StyledBackground);
    setMouseTracking(true);

	ui.scrollArea->setWidget(wnd_layout_);


    // connect
	connect(wnd_layout_, &CCustomBoxView::boxClicked, 
        this, &CBackendWnd::event_locker_cell_clicked);
	connect(ui.combo_begno, SIGNAL(currentIndexChanged(int)),
		ui.combo_endno, SLOT(setCurrentIndex(int)));

	timer_->setInterval(20 * 1000);
    connect(timer_, &QTimer::timeout, this, [&]() { emit backToHome(); });
}

CBackendWnd::~CBackendWnd()
{

}

void CBackendWnd::LoadData()
{
    update_panel_layout();
    update_panel_dashboard();
    update_panel_manager_card();
    update_panel_payment_manager();

	UpdatePanelAdvance();
}

void CBackendWnd::init()
{
	auto* group = new QButtonGroup(this);
	group->addButton(ui.btn_navi1, 0);
	group->addButton(ui.btn_navi2, 1);
	group->addButton(ui.btn_navi3, 2);
	group->addButton(ui.btn_navi4, 3);
	group->addButton(ui.btn_navi5, 4);
    group->addButton(ui.btn_navi6, 5);
	connect(group, SIGNAL(buttonClicked(int)), this, SLOT(event_navi_btn_clicked(int)));
	ui.stackedWidget->setCurrentIndex(0);

	// init panels
    init_panel_layout();
	init_panel_inquery_order();
    init_panel_advance();
    init_panel_paid_details();
    init_panel_manager_card();
    init_panel_payment_manager();
}

void CBackendWnd::init_panel_layout()
{
    // 布局表格
    QStringList list1 = { tr("Index"), tr("TypeList") };
    model_layout_->setHorizontalHeaderLabels(list1);
    model_layout_->setColumnCount(list1.size());
    ui.tb_layout->setModel(model_layout_);
    ui.tb_layout->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    ui.tb_layout->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
    ui.tb_layout->horizontalHeader()->resizeSection(0, 120);
    ui.tb_layout->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);


    // 开门板配置表格
    QStringList list2 = {
        tr("Index"),
        tr("Pcbno"),
        tr("Count"),
        tr("")
    };
    model_dcb_->setHorizontalHeaderLabels(list2);
    model_dcb_->setColumnCount(list2.size());
    ui.tb_dcb->setModel(model_dcb_);
    ui.tb_dcb->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    ui.tb_dcb->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    ui.tb_dcb->horizontalHeader()->resizeSection(0, 100);
    ui.tb_dcb->horizontalHeader()->resizeSection(1, 100);
    ui.tb_dcb->horizontalHeader()->resizeSection(2, 100);
    ui.tb_dcb->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);

}

void CBackendWnd::init_panel_inquery_order()
{
    QStringList list5 = {
        tr("Index"),
        tr("Order ID"),
        tr("Locker No."),
        tr("User ID"),
//        tr("User code"),
        tr("Status"),
        tr("Locker Type"),
        tr("Begin Time"),
        tr("End Time"),
        tr("Is Confirmed") };
    model_query_->setHorizontalHeaderLabels(list5);
    model_query_->setColumnCount(list5.size());

    ui.tb_record->setModel(model_query_);
    ui.tb_record->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui.tb_record->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    connect(ui.combo_record_type, SIGNAL(currentIndexChanged(int)), this, SLOT(record_type_changed(int)));


	ui.combo_order_status->clear();
	ui.combo_order_status->insertItem(0, tr("All"), 0);
	ui.combo_order_status->insertItem(1, tr("Prepared"), zl::EOrderStatus_Prepared);
	ui.combo_order_status->insertItem(2, tr("Using"), zl::EOrderStatus_Using);
	ui.combo_order_status->insertItem(3, tr("Finished"), zl::EOrderStatus_Finished);
	ui.combo_order_status->insertItem(4, tr("Completed"), zl::EOrderStatus_Completed);
	ui.combo_order_status->insertItem(5, tr("Error"), zl::EOrderStatus_Error);
	ui.combo_order_status->insertItem(6, tr("Expired"), zl::EOrderStatus_Expired);
	ui.combo_order_status->insertItem(7, tr("Locked"), zl::EOrderStatus_Locked);
	ui.combo_order_status->insertItem(8, tr("Canceled"), zl::EOrderStatus_Canceled);
	ui.combo_order_status->insertItem(9, tr("ManualFinished"), zl::EOrderStatus_ManualFinished);

	ui.combo_order_type->clear();
	ui.combo_order_type->insertItem(0, tr("All"), -1);
    ui.combo_order_type->insertItem(1, tr("Confirmed"), 0);
    ui.combo_order_type->insertItem(2, tr("Not Confirmed"), 1);

	ui.edt_begin_date->setDateTime(QDateTime::currentDateTime());
    ui.edt_end_date->setDateTime(QDateTime::currentDateTime().addDays(1));
}

void CBackendWnd::init_panel_manager_card()
{
    ui.tb_manager_card->setModel(model_manager_card_);
    ui.tb_manager_card->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui.tb_manager_card->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    QStringList list4 = { tr("Card Status"), tr("Card No.") };
    model_manager_card_->setHorizontalHeaderLabels(list4);
    model_manager_card_->setColumnCount(list4.size());
}

void CBackendWnd::init_panel_advance()
{
    ui.combo_device_portname->clear();
#ifdef Q_OS_WIN32
    for (int i = 1; i < 20; ++i)
    {
        ui.combo_device_portname->addItem(QString("COM%1").arg(i));
    }
#elif __arm__
    ui.combo_device_portname->addItem("/dev/ttymxc1");
    ui.combo_device_portname->addItem("/dev/ttymxc2");
    ui.combo_device_portname->addItem("/dev/ttymxc3");
    ui.combo_device_portname->addItem("/dev/ttymxc4");
#endif // __arm__
}

void CBackendWnd::init_panel_payment_manager()
{
    ui.tb_payment->setModel(model_payment_);
    ui.tb_payment->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui.tb_payment->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    QStringList list = { tr("Payment plan ID"), tr("Payment plan alias") };
    model_payment_->setHorizontalHeaderLabels(list);
    model_payment_->setColumnCount(list.size());
}

void CBackendWnd::init_panel_paid_details()
{
    ui.combo_pay_type->insertItem(0, tr("All"), "");
    ui.combo_pay_type->insertItem(1, tr("Cash"), "0");
    ui.combo_pay_type->insertItem(2, tr("WechatPay"), "1");
    ui.combo_pay_type->insertItem(3, tr("Alipay"), "2");
    ui.edt_begin_date->setDateTime(QDateTime::currentDateTime());
    ui.edt_end_date->setDateTime(QDateTime::currentDateTime());
    ui.label_paytype->setHidden(true);
    ui.label_total->setHidden(true);
    ui.edt_total_fee->setHidden(true);
    ui.combo_pay_type->setHidden(true);
}

void CBackendWnd::update_panel_layout()
{
    // 更新布局配置信息
    zl::LockerLayout layout = APPMODEL()->ZLBaseCfg().layout_list;
    model_layout_->setRowCount(0);
    for (auto l : layout)
    {
        QList<QStandardItem*> row;
        row.append(new QStandardItem(QString::number(l.index)));
        row.append(new QStandardItem(l.typestr.c_str()));
        model_layout_->appendRow(row);
    }

    // 更新开门板配置信息
    std::vector<zl::DoorControlBoard> dcb_list = APPMODEL()->ZLBaseCfg().dcb_list;
    model_dcb_->setRowCount(0);
    for (auto d : dcb_list)
    {
        QList<QStandardItem*> row;
        row.append(new QStandardItem(QString::number(d.index)));
        row.append(new QStandardItem(QString::number(d.col)));
        row.append(new QStandardItem(QString::number(d.count)));
        row.append(new QStandardItem(tr("Double click to edit")));
        model_dcb_->appendRow(row);
        store_data_to_model_dcb(d, model_dcb_->index(model_dcb_->rowCount() - 1, 0));
    }
}

void CBackendWnd::update_panel_dashboard()
{
    zl::LockerVec lockers;
    zl::CCabinetManager::Instance()->GetAllLockers(lockers);
    zl::LockerLayout layout = APPMODEL()->ZLBaseCfg().layout_list;

	wnd_layout_->SetLayout(layout);
    wnd_layout_->SetData(lockers, APPMODEL()->CabinetInfo().tag_number);

	ui.combo_begno->clear();
	ui.combo_endno->clear();
	ui.combo_locker_no->clear();
    ui.combo_locker_no->insertItem(0, tr("All"));
    for (size_t i = 1; i <= lockers.size(); ++i)
	{
        ui.combo_begno->insertItem(i, QString::number(i+APPMODEL()->CabinetInfo().tag_number));
        ui.combo_endno->insertItem(i, QString::number(i+APPMODEL()->CabinetInfo().tag_number));
        ui.combo_locker_no->insertItem(i, QString::number(i+APPMODEL()->CabinetInfo().tag_number));
	}
    ui.combo_locker_no->setCurrentIndex(0);
}

void CBackendWnd::update_panel_manager_card()
{
	auto pfconvert = [](int32_t v)-> QString {
		switch (v)
		{
        case 0: return tr("Locked");
        case 1: return tr("Root");
        case 2: return tr("Normal");
		default: return tr("Unknow");
		}
	};

	zl::ManagerCardVec cardvec;
	zl::CCabinetManager::Instance()->GetManagerCardList(cardvec);
	
	model_manager_card_->setRowCount(0);
	std::for_each(cardvec.begin(), cardvec.end(), [&](const zl::ManagerCard& card) {
		QList<QStandardItem*> row;
		row.append(new QStandardItem(pfconvert(card.status)));
		row.append(new QStandardItem(card.cardno.c_str()));

		model_manager_card_->appendRow(row);
	});
}

void CBackendWnd::update_panel_advance()
{
	auto cabinetinfo = APPMODEL()->Config().cabinet;
    ui.edt_cabinet_no->setText(cabinetinfo.id.c_str());
    ui.edt_cabinet_name->setText(cabinetinfo.name.c_str());
    ui.combo_device_portname->setCurrentText(cabinetinfo.validator_com.c_str());
    ui.edt_device_validator_baud->setText(QString::number(cabinetinfo.validator_baud));
    ui.combo_device_validator_type->setCurrentIndex(cabinetinfo.validator_type);
    ui.edt_tag_number->setText(QString::number(cabinetinfo.tag_number));

	auto svrinfo = APPMODEL()->Config().server;
    ui.edt_server_addr1->setText(svrinfo.remote_addr.c_str());
    ui.edt_server_port1->setText(QString::number(svrinfo.remote_port));
    ui.edt_server_port2->setText(QString::number(svrinfo.local_port));
    ui.edt_server_corp_id->setText(svrinfo.corp_id.c_str());
    ui.edt_server_corp_name->setText(svrinfo.corp_name.c_str());
    ui.edt_server_payplat_uri->setText(svrinfo.payplat_uri.c_str());
}

void CBackendWnd::update_panel_payment_manager()
{
    // 获取所有付费方案列表
    std::vector<zl::CPaymentPlan> planlist;
    auto ret = zl::CPaymentManager::Instance()->RetrievePaymentPlan(planlist);
    if (ret != zl::EResult_Success)
    {
        return;
    }

    // 更新表格和复选框信息
    model_payment_->setRowCount(0);
    ui.combo_small_payment->clear();
    ui.combo_medium_payment->clear();
    ui.combo_large_payment->clear();
    ui.combo_extra_payment->clear();
    for (auto& plan : planlist)
    {
        QList<QStandardItem*> row;
        row.append(new QStandardItem(QString::number(plan.id())));
        row.append(new QStandardItem(plan.alias().c_str()));
        model_payment_->appendRow(row);

        ui.combo_small_payment->addItem(plan.alias().c_str(), plan.id());
        ui.combo_medium_payment->addItem(plan.alias().c_str(), plan.id());
        ui.combo_large_payment->addItem(plan.alias().c_str(), plan.id());
        ui.combo_extra_payment->addItem(plan.alias().c_str(), plan.id());
    }

    // 根据配置选项更新支付方式设置
    ui.ck_enable_alipay->setChecked(APPMODEL()->Config().payment.enable_alipay == 1);
    ui.ck_enable_wechatpay->setChecked(APPMODEL()->Config().payment.enable_wechatpay == 1);
    ui.ck_enable_cash->setChecked(APPMODEL()->Config().payment.enable_cash == 1);
    ui.ck_enable_onecode->setChecked(APPMODEL()->Config().payment.enable_onecode == 1);

    auto i1 = ui.combo_small_payment->findData(APPMODEL()->Config().payment.payment_small);
    auto i2 = ui.combo_medium_payment->findData(APPMODEL()->Config().payment.payment_medium);
    auto i3 = ui.combo_large_payment->findData(APPMODEL()->Config().payment.payment_large);
    auto i4 = ui.combo_extra_payment->findData(APPMODEL()->Config().payment.payment_extra_large);
    ui.combo_small_payment->setCurrentIndex(i1);
    ui.combo_medium_payment->setCurrentIndex(i2);
    ui.combo_large_payment->setCurrentIndex(i3);
    ui.combo_extra_payment->setCurrentIndex(i4);
}

QString CBackendWnd::convert_billing_unit(int32_t unit)
{
    switch (unit)
    {
    case 0: return tr("hours");
    case 1: return tr("day");
    default: return tr("unknown unit");
    }
}

void CBackendWnd::query_order()
{
    std::string begdt = ui.edt_begin_date->date().toString("yyyy-MM-dd").toStdString();
    std::string enddt = ui.edt_end_date->date().toString("yyyy-MM-dd").toStdString();
    std::string phone = ui.edt_phone->text().toStdString();
    int32_t status = ui.combo_order_status->currentData().toInt();
    int32_t locker = ui.combo_locker_no->currentIndex();
    int32_t ordertype = ui.combo_order_type->currentData().toInt();

    zl::OrderVec ordervec;
    int32_t ret = zl::COrderManager::Instance()->GetAllOrders(
                ordervec,
                begdt,
                enddt,
                phone,
                status,
                ordertype,
                locker);
    if (ret != zl::EResult_Success)
    {
        CToastBox::Error(this, "", tr("Inquery order failed"));
        return;
    }

    auto pfconvert1 = [](int32_t v) -> QString {
        switch (v)
        {
        case zl::EOrderStatus_Prepared:		return tr("Prepared");
        case zl::EOrderStatus_Using:		return tr("Using");
        case zl::EOrderStatus_Finished:		return tr("Finished");
        case zl::EOrderStatus_Completed:	return tr("Completed");
        case zl::EOrderStatus_Error:		return tr("Error");
        case zl::EOrderStatus_Expired:		return tr("Expired");
        case zl::EOrderStatus_Locked:		return tr("Locked");
        case zl::EOrderStatus_Canceled:		return tr("Canceled");
        case zl::EOrderStatus_ManualFinished:	return tr("ManualFinished");

        default: return tr("Unknow");

        }
    };
    auto pfconvert2 = [](int32_t v) -> QString {
        switch (v)
        {
        case zl::ELockerType_Small:		return tr("Small");
        case zl::ELockerType_Medium:	return tr("Medium");
        case zl::ELockerType_Large:		return tr("Large");
        case zl::ELockerType_ExtraLarge: return tr("ExtraLarge");

        default:						return tr("DefaultSize");
        }
    };
    auto pfconvert3 = [](int32_t v) -> QString {
        switch (v)
        {
        case 0:		return tr("Confirmed");
        default:	return tr("Not Confirmed");
        }
    };
    auto pfconvert4 = [](int32_t boxno) -> QString {
        return QString("%1").arg(boxno + APPMODEL()->CabinetInfo().tag_number);
    };

    // update table order
    model_query_->setRowCount(0);
    int32_t index = 0;
    std::for_each(ordervec.begin(), ordervec.end(), [&](const zl::Order& order) {
        QList<QStandardItem*> row;
        row.append(new QStandardItem(QString::number(index++)));
        row.append(new QStandardItem(order.order_id.c_str()));
        row.append(new QStandardItem(pfconvert4(order.box_no)));
        row.append(new QStandardItem(order.user_id.c_str()));
        row.append(new QStandardItem(pfconvert1(order.status)));
        row.append(new QStandardItem(pfconvert2(order.box_type)));
        row.append(new QStandardItem(order.begin_time.c_str()));
        row.append(new QStandardItem(order.end_time.c_str()));
        row.append(new QStandardItem(pfconvert3(order.confirmed)));

        model_query_->appendRow(row);
    });
}

void CBackendWnd::query_oper()
{
    std::string begdt = ui.edt_begin_date->date().toString("yyyy-MM-dd").toStdString();
    std::string enddt = ui.edt_end_date->date().toString("yyyy-MM-dd").toStdString();
    std::string phone = ui.edt_phone->text().toStdString();
    int32_t locker = ui.combo_locker_no->currentIndex();

    zl::OperLogVec operlogvec;
    int32_t ret = zl::COperLogManager::Instance()->GetAllOperLogs(
                operlogvec,
                begdt,
                enddt,
                phone,
                locker);
    if (ret != zl::EResult_Success)
    {
        CToastBox::Error(this, "", tr("Inquery oper log failed"));
        return;
    }

    auto pfconvert5 = [](int32_t boxno) -> QString {
        return QString("%1").arg(boxno + APPMODEL()->CabinetInfo().tag_number);
    };

    // update table order
    model_query_->setRowCount(0);
    int32_t index = 0;
    std::for_each(operlogvec.begin(), operlogvec.end(), [&](const zl::OperLog& operlog) {
        QList<QStandardItem*> row;
        row.clear();
        row.append(new QStandardItem(QString::number(index++)));
        row.append(new QStandardItem(pfconvert5(operlog.box_no)));
        row.append(new QStandardItem(operlog.action.c_str()));
        row.append(new QStandardItem(operlog.type.c_str()));
        row.append(new QStandardItem(operlog.account.c_str()));
        row.append(new QStandardItem(operlog.time.c_str()));

        model_query_->appendRow(row);
    });
}

void CBackendWnd::query_payment()
{
    std::string begdt = ui.edt_begin_date->date().toString("yyyy-MM-dd").toStdString();
    std::string enddt = ui.edt_end_date->date().toString("yyyy-MM-dd").toStdString();
    std::string type = ui.combo_pay_type->currentData().toString().toStdString();

    std::vector<zl::PaidDetail> detailslist;
    int32_t ret = zl::CPaymentManager::Instance()->RetrievePaidDetails(
        detailslist, begdt, enddt, type);
    if (ret != zl::EResult_Success)
    {
        CToastBox::Error(this, "", tr("Inquery paid details failed"));
        return;
    }

    // tools
    auto convert_pay_type = [](const std::string& t) -> QString {
        if (t == "0") return tr("Cash");
        else if (t == "1") return tr("WechatPay");
        else if (t == "2") return tr("Alipay");
        else return tr("Unknown");
    };

    // update table view
    model_query_->setRowCount(0);
    int32_t index = 1;
    int32_t total = 0;
    std::for_each(detailslist.begin(), detailslist.end(), [&](const zl::PaidDetail& pd) {
        QList<QStandardItem*> row;
        row.append(new QStandardItem(QString::number(index++)));
        row.append(new QStandardItem(QString::number(pd.box_id)));
        row.append(new QStandardItem(QString("%1").arg((float)pd.fee_paid / 100.0, 0, 'g', 2)));
        row.append(new QStandardItem(pd.pay_time.c_str()));
        row.append(new QStandardItem(convert_pay_type(pd.pay_mode)));
        row.append(new QStandardItem(pd.order_id.c_str()));
        row.append(new QStandardItem(pd.pay_order_id.c_str()));
        model_query_->appendRow(row);
        total += pd.fee_paid;
    });

    ui.edt_total_fee->setText(tr("%1").arg((float)total / 100));
}

void CBackendWnd::UpdatePanelAdvance()
{
	update_panel_advance();
}

void CBackendWnd::UpdateLockerStatus()
{
	zl::LockerVec lockers;
	zl::CCabinetManager::Instance()->GetAllLockers(lockers);
    wnd_layout_->SetData(lockers, APPMODEL()->CabinetInfo().tag_number);
}

void CBackendWnd::SetLevel(int32_t t)
{
    // todo
    return;
}

void CBackendWnd::SetAccount(string account)
{
    admin_account = account;
}

void CBackendWnd::on_btnl_back_clicked()
{
    if (ui.stackedWidget->currentIndex() == 0)
    {
        // back to home
        emit backToHome();
    }

    ui.stackedWidget->setCurrentIndex(0);
    ui.lb_title->setText(tr("Backend Managerment"));
}

void CBackendWnd::event_locker_cell_clicked(int32_t lockerno)
{
    ui.combo_begno->setCurrentText(QString::number(lockerno+APPMODEL()->CabinetInfo().tag_number));
    ui.combo_endno->setCurrentText(QString::number(lockerno+APPMODEL()->CabinetInfo().tag_number));
}

void CBackendWnd::on_btni_open_clicked()
{
    ui.btni_open->setDisabled(true);
    QTimer::singleShot(1500, [this]() {
        ui.btni_open->setDisabled(false);
    });

    int32_t begno = ui.combo_begno->currentText().toInt()-APPMODEL()->CabinetInfo().tag_number;
    int32_t endno = ui.combo_endno->currentText().toInt()-APPMODEL()->CabinetInfo().tag_number;
	for (int32_t i = begno; i <= endno; ++i)
	{
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        zl::CCabinetManager::Instance()->OpenBox(i);
        OperLog log = zl::COperLogManager::Instance()->CreateOperLog();
        log.cabinet_no = CabinetID().c_str();
        log.box_no = i;
        log.action = tr("Background opening").toStdString();
        log.type = tr("Administrators").toStdString();
        log.account = admin_account;
        zl::COperLogManager::Instance()->CommitOperLog(log);
	}
}

void CBackendWnd::on_btnw_clean_clicked()
{
    int32_t boxno = ui.combo_begno->currentText().toInt()-APPMODEL()->CabinetInfo().tag_number;

    // 查询该格口上的订单信息，如果有则清除订单
    zl::Order order;
	auto ret = zl::COrderManager::Instance()->GetOrderByBoxno(order, boxno);
    if (ret == zl::EResult_Success)
    {
        // 清除订单信息
        ret = zl::COrderManager::Instance()->CancelOrder(order);
        if (ret != zl::EResult_Success)
        {
            // 清除订单失败
            CToastBox::Error(this, "", tr("Cancel order failed"));
            return;
        }
    }

    // 清除格口的占用状态
    zl::CCabinetManager::Instance()->CleanBox(boxno);

    // 操作日志记录
    OperLog log = zl::COperLogManager::Instance()->CreateOperLog();
    log.cabinet_no = CabinetID().c_str();
    log.box_no = boxno;
    log.action = tr("Background clear").toStdString();
    log.type = tr("Administrators").toStdString();
    log.account = admin_account;
    zl::COperLogManager::Instance()->CommitOperLog(log);

    CToastBox::Info(this, "", tr("Operation succeeded"));
}

void CBackendWnd::on_btnd_lock_clicked()
{
    int32_t begno = ui.combo_begno->currentText().toInt() - APPMODEL()->CabinetInfo().tag_number;
    int32_t endno = ui.combo_endno->currentText().toInt() - APPMODEL()->CabinetInfo().tag_number;;

	for (int32_t i = begno; i <= endno; ++i)
	{
		int32_t ret = zl::CCabinetManager::Instance()->LockBox(i);
	}
}

void CBackendWnd::on_btns_unlock_clicked()
{
    int32_t begno = ui.combo_begno->currentText().toInt() - APPMODEL()->CabinetInfo().tag_number;;
    int32_t endno = ui.combo_endno->currentText().toInt() - APPMODEL()->CabinetInfo().tag_number;;

	for (int32_t i = begno; i <= endno; ++i)
	{
		int32_t ret = zl::CCabinetManager::Instance()->UnlockBox(i);
	}
}

void CBackendWnd::on_btns_add_row_clicked()
{
	QList<QStandardItem*> row;
	row.append(new QStandardItem(QString("%1").arg(model_layout_->rowCount() + 1)));
    row.append(new QStandardItem(""));
	model_layout_->appendRow(row);
}

void CBackendWnd::on_btnd_del_row_clicked()
{
	model_layout_->removeRow(model_layout_->rowCount() - 1);
}

void CBackendWnd::on_btni_save_layout_clicked()
{
    // 检查是否有仍然在使用的订单
    zl::OrderVec orders;
    auto ret = zl::COrderManager::Instance()->GetAllUsingOrders(orders);
    if (ret == EResult_Success && orders.size() > 0)
    {
        CToastBox::Info(this, "", tr("Some boxes are using, can not set layout!"));
        return;
    }
	
    // 获取布局配置
    zl::LockerLayout layout;
	for (int i = 0; i < model_layout_->rowCount(); ++i)
    {
        auto ti = model_layout_->index(i, 0).data(Qt::DisplayRole).toInt();
        auto ts = model_layout_->index(i, 1).data(Qt::DisplayRole).toString().toStdString();
        layout.push_back({ti, ts});
	}

    // 获取开门板配置
    std::vector<zl::DoorControlBoard> dcb_list;
    for (int i = 0; i < model_dcb_->rowCount(); ++i)
    {
        zl::DoorControlBoard dcb;
        dcb.index = model_dcb_->index(i, 0).data().toInt();
        read_data_from_model_dcb(dcb, model_dcb_->index(i, 0));
        dcb_list.push_back(dcb);
    }

    // 保存新的布局数据
    auto cfg = APPMODEL()->ZLBaseCfg();
    cfg.layout_list = layout;
    cfg.dcb_list = dcb_list;
    APPMODEL()->SetZLBaseCfg(cfg);
    APPMODEL()->WriteConfiguration();

    // 更新配置信息
    zl::CCabinetManager::Instance()->ResetZLBaseConfig(cfg);
    update_panel_layout();
    update_panel_dashboard();

    CToastBox::Info(this, "", tr("Update cabinet layout success"));
}

void CBackendWnd::on_btns_add_dcb_clicked()
{
    QList<QStandardItem*> row;
    row.append(new QStandardItem(QString("%1").arg(model_dcb_->rowCount() + 1)));
    row.append(new QStandardItem(""));
    row.append(new QStandardItem(""));
    row.append(new QStandardItem(tr("Double click to edit")));
    model_dcb_->appendRow(row);
}

void CBackendWnd::on_btnd_del_dcb_clicked()
{
    model_dcb_->removeRow(model_dcb_->rowCount() - 1);
}

void CBackendWnd::on_tb_dcb_doubleClicked(const QModelIndex &index)
{
    // 只处理第四个单元格点击事件
    if (index.column() != 3)
    {
        return;
    }
    auto i = model_dcb_->index(index.row(), 0);

    // 显示编辑对话框
    CDoorControlBoardEditDlg dlg(this);
    frmInputNew::Instance()->setParent(&dlg);
    // 获取当前单元格数据
    if (model_dcb_->data(i, ROLE_DCB_FLAG).toInt() == 1)
    {
        zl::DoorControlBoard dcb;
        read_data_from_model_dcb(dcb, i);
        dlg.SetData(dcb);
    }

    // 显示对话框
    if (dlg.exec() != QDialog::Accepted)
    {
        frmInputNew::Instance()->setParent(this);
        return;
    }
    frmInputNew::Instance()->setParent(this);

    // 更新数据到表格中
    auto dcb = dlg.GetData();
    auto index_col = model_dcb_->index(index.row(), 1);
    auto index_count = model_dcb_->index(index.row(), 2);
    model_dcb_->setData(index_col, QString::number(dcb.col), Qt::DisplayRole);
    model_dcb_->setData(index_count, QString::number(dcb.count), Qt::DisplayRole);
    store_data_to_model_dcb(dcb, i);
}

void CBackendWnd::on_btns_register_card_clicked()
{
	std::string cardno = ui.edt_manager_card->text().toStdString();
	ui.edt_manager_card->clear();
	ui.edt_manager_card->setFocus();

	if (cardno.empty())
	{
        CToastBox::Error(this, "", tr("Empty manager card no"));
		return;
	}

	auto ret = zl::CCabinetManager::Instance()->RegisterManagerCard(cardno);
	if (ret != zl::EResult_Success)
	{
        CToastBox::Error(this, "", tr("Register manager card failed"));
	}
	else
	{
        update_panel_manager_card();
        CToastBox::Success(this, "", tr("Register success"));
    }
}

void CBackendWnd::on_btni_set_root_card_clicked()
{
    // todo
}

void CBackendWnd::on_btnw_set_normal_card_clicked()
{
    // todo
}

void CBackendWnd::on_btnw_lock_card_clicked()
{
	auto indexlist =  ui.tb_manager_card->selectionModel()->selectedRows(1);
	if (indexlist.isEmpty())
	{
        CToastBox::Error(this, "", tr("Please selecte a manager card first"));
		return;
	}

	auto cardno = indexlist.first().data(Qt::DisplayRole).toString().toStdString();
    if(cardno == admin_account)
    {
        CToastBox::Error(this, "", tr("Can`t operator youself"));
        return ;
    }

	auto ret = zl::CCabinetManager::Instance()->UpdateManagerCardStatus(cardno, zl::ECardStatus_Locked);
	if (ret != zl::EResult_Success)
	{
        CToastBox::Error(this, "", tr("Lock manager card failed"));
	}
	else
	{
        update_panel_manager_card();
	}
}

void CBackendWnd::on_btns_unlock_card_clicked()
{
	auto indexlist = ui.tb_manager_card->selectionModel()->selectedRows(1);
	if (indexlist.isEmpty())
	{
        CToastBox::Error(this, "", tr("Please selecte a manager card first"));
		return;
	}

	auto cardno = indexlist.first().data(Qt::DisplayRole).toString().toStdString();
    if(cardno == admin_account)
    {
        CToastBox::Error(this, "", tr("Can`t operator youself"));
        return ;
    }

	auto ret = zl::CCabinetManager::Instance()->UpdateManagerCardStatus(cardno, zl::ECardStatus_Normal);
	if (ret != zl::EResult_Success)
	{
        CToastBox::Error(this, "", tr("Unlock manager card failed"));
	}
	else
	{
        update_panel_manager_card();
	}
}

void CBackendWnd::on_btnd_del_card_clicked()
{
	auto indexlist = ui.tb_manager_card->selectionModel()->selectedRows(1);
	if (indexlist.isEmpty())
	{
        CToastBox::Error(this, "", tr("Please selecte a manager card first"));
		return;
	}

	auto cardno = indexlist.first().data(Qt::DisplayRole).toString().toStdString();
    if(cardno == admin_account)
    {
        CToastBox::Error(this, "", tr("Can`t operator youself"));
        return ;
    }

	auto ret = zl::CCabinetManager::Instance()->DeleteManagerCard(cardno);
	if (ret != zl::EResult_Success)
	{
        CToastBox::Error(this, "", tr("Delete manager card failed"));
	}
	else
	{
        update_panel_manager_card();
        CToastBox::Info(this, "", tr("Operation succeeded"));
	}
}

void CBackendWnd::on_btns_query_record_clicked()
{
    if(ui.combo_record_type->currentIndex() == 0)
    {
        query_order();
    }
    else if(ui.combo_record_type->currentIndex() == 1)
    {
        query_oper();
    }
    else if(ui.combo_record_type->currentIndex() == 2)
    {
        query_payment();
    }

}

void CBackendWnd::on_btni_save_config_clicked()
{
	auto config = APPMODEL()->Config();

    config.cabinet.id = ui.edt_cabinet_no->text().toStdString();
    config.cabinet.name = ui.edt_cabinet_name->text().toStdString();
    config.cabinet.validator_com = ui.combo_device_portname->currentText().toStdString();
    config.cabinet.validator_baud = ui.edt_device_validator_baud->text().toInt();
    config.cabinet.validator_type = ui.combo_device_validator_type->currentIndex();
    config.cabinet.tag_number = ui.edt_tag_number->text().toInt();

    config.server.remote_addr = ui.edt_server_addr1->text().toStdString();
    config.server.remote_port = ui.edt_server_port1->text().toInt();
    config.server.local_port = ui.edt_server_port2->text().toInt();
    config.server.auth_id = "0013-0008";
    config.server.auth_name = "0013-0008";
    config.server.site_id = "zhilaiweb";
    config.server.site_name = "zhilaiweb";
    config.server.corp_id = ui.edt_server_corp_id->text().toStdString();
    config.server.corp_name = ui.edt_server_corp_name->text().toStdString();
    config.server.payplat_uri = ui.edt_server_payplat_uri->text().toStdString();

    // 保存配置数据
	APPMODEL()->SetConfig(config);
    APPMODEL()->WriteConfiguration();
    CToastBox::Success(this, "", tr("Save configuration success"));
    emit configChanged();
}

void CBackendWnd::on_btnd_exit_clicked()
{
	emit exitApp();
    system("reboot");
}

void CBackendWnd::on_btnp_system_settings_clicked()
{
    event_navi_btn_clicked(6);
}

void CBackendWnd::on_btns_add_payment_clicked()
{
    CPaymentPlanEditDlg dlg(this);
    frmInputNew::Instance()->setParent(&dlg);
    if (dlg.exec() != QDialog::Accepted)
    {
        frmInputNew::Instance()->setParent(this);
        return;
    }
    frmInputNew::Instance()->setParent(this);

    auto plan = dlg.GetData();
    auto ret = zl::CPaymentManager::Instance()->CreatePaymentPlan(plan);
    if (ret != zl::EResult_Success)
    {
        CToastBox::Error(this, tr(""), tr("Add payment plan failed"));
        return;
    }

    // 更新支付方案列表
    update_panel_payment_manager();
}

void CBackendWnd::on_btnw_modify_payment_clicked()
{
    auto indexlist = ui.tb_payment->selectionModel()->selectedRows(1);
    if (indexlist.isEmpty())
    {
        CToastBox::Error(this, "", tr("Please selecte a payment plan first"));
        return;
    }

    auto index = model_payment_->index(indexlist.first().row(), 0);
    auto planid = index.data(Qt::DisplayRole).toInt();
    zl::CPaymentPlan plan;
    plan.set_id(planid);
    zl::CPaymentManager::Instance()->RetrievePaymentPlan(planid, plan);

    CPaymentPlanEditDlg dlg(this);
    frmInputNew::Instance()->setParent(&dlg);
    dlg.SetData(plan);
    if (dlg.exec() != QDialog::Accepted)
    {
        frmInputNew::Instance()->setParent(this);
        return;
    }
    frmInputNew::Instance()->setParent(this);

    zl::CPaymentPlan new_plan = dlg.GetData();
    auto ret = zl::CPaymentManager::Instance()->UpdatePaymentPlan(new_plan);
    if (ret != zl::EResult_Success)
    {
        CToastBox::Error(this, "", tr("Modify payment plan failed"));
        return;
    }

    // 更新支付方案列表
    update_panel_payment_manager();
}

void CBackendWnd::on_btnd_delete_payment_clicked()
{
    auto indexlist = ui.tb_payment->selectionModel()->selectedRows(1);
    if (indexlist.isEmpty())
    {
        CToastBox::Error(this, "", tr("Please selecte a payment plan first"));
        return;
    }

    // 删除指定的付费方案
    auto index = model_payment_->index(indexlist.first().row(), 0);
    auto planid = index.data(Qt::DisplayRole).toInt();
    auto ret = zl::CPaymentManager::Instance()->DeletePaymentPlan(planid);
    if (ret != zl::EResult_Success)
    {
        CToastBox::Error(this, "", tr("Delete payment plan failed"));
        return;
    }

    // 更新支付方案列表
    update_panel_payment_manager();
}

void CBackendWnd::on_btni_save_payment_conf_clicked()
{
    int32_t smallid = ui.combo_small_payment->currentData().toInt();
    int32_t mediumid = ui.combo_medium_payment->currentData().toInt();
    int32_t largeid = ui.combo_large_payment->currentData().toInt();
    int32_t extraid = ui.combo_extra_payment->currentData().toInt();
    int32_t enable_alipay = ui.ck_enable_alipay->isChecked() ? 1 : 0;
    int32_t enable_wechatpay = ui.ck_enable_wechatpay->isChecked() ? 1 : 0;
    int32_t enable_cash = ui.ck_enable_cash->isChecked() ? 1 : 0;
    int32_t enable_onecode = ui.ck_enable_onecode->isChecked() ? 1 : 0;

    // 更新配置信息
    zl::PaymentConf conf;
    conf.payment_small = smallid;
    conf.payment_medium = mediumid;
    conf.payment_large = largeid;
    conf.payment_extra_large = extraid;
    conf.enable_alipay = enable_alipay;
    conf.enable_wechatpay = enable_wechatpay;
    conf.enable_cash = enable_cash;
    conf.enable_onecode = enable_onecode;
    APPMODEL()->SetPaymentCfg(conf);
    APPMODEL()->WriteConfiguration();

    // 若没有选择任何付费方式，弹出提示信息
    if(enable_alipay || enable_wechatpay || enable_cash || enable_onecode)
    {
        CToastBox::Info(this, "", tr("Operation succeeded"));
    }
    else
    {
        CToastBox::Warn(this, "", tr("Operation succeeded,No payment method selected"));
    }
}

void CBackendWnd::event_navi_btn_clicked(int index)
{
    ui.stackedWidget->setCurrentIndex(index + 1);

    QString title = "";
    switch (index + 1)
    {
    case 1:
    {
        title = tr("Dashboard");
        break;
    }
    case 2:
    {
        title = tr("Param Settings");
        update_panel_layout();
        break;
    }
    case 3:
    {
        title = tr("Account Managerment");
        break;
    }
    case 4:
    {
        title = tr("Record Query");
        break;
    }
    case 5:
    {
        title = tr("Payment Managerment");
        break;
    }
    case 6:
    {
        title = tr("Advance Settings");
        break;
    }
    case 7:
    {
        title = tr("System Settings");
        break;
    }
    default:
        return;
    }
    ui.lb_title->setText(title);
}

void CBackendWnd::record_type_changed(int index)
{
    if(index == 0)
    {
        ui.label_paytype->setHidden(true);
        ui.label_total->setHidden(true);
        ui.edt_total_fee->setHidden(true);
        ui.combo_pay_type->setHidden(true);
        ui.label_7->setHidden(false);
        ui.label_9->setHidden(false);
        ui.label_5->setHidden(false);
        ui.label_8->setHidden(false);
        ui.combo_locker_no->setHidden(false);
        ui.edt_phone->setHidden(false);
        ui.combo_order_status->setHidden(false);
        ui.combo_order_type->setHidden(false);
        QStringList list5 = {
            tr("Index"),
            tr("Order ID"),
            tr("Locker No."),
            tr("User ID"),
            tr("Status"),
            tr("Locker Type"),
            tr("Begin Time"),
            tr("End Time"),
            tr("Is Confirmed") };
        model_query_->setHorizontalHeaderLabels(list5);
        model_query_->setColumnCount(list5.size());
    }
    else if(index == 1)
    {
        ui.label_paytype->setHidden(true);
        ui.label_total->setHidden(true);
        ui.edt_total_fee->setHidden(true);
        ui.combo_pay_type->setHidden(true);
        ui.label_5->setHidden(true);
        ui.label_8->setHidden(true);
        ui.label_7->setHidden(false);
        ui.label_9->setHidden(false);
        ui.combo_locker_no->setHidden(false);
        ui.edt_phone->setHidden(false);
        ui.combo_order_status->setHidden(true);
        ui.combo_order_type->setHidden(true);
        // 操作日志
        QStringList list7 = {
            tr("ID"),
            tr("Locker No."),
            tr("Action"),
            tr("Type"),
            tr("Account"),
            tr("Time") };
        model_query_->setHorizontalHeaderLabels(list7);
        model_query_->setColumnCount(list7.size());
    }
    else if(index == 2)
    {
        ui.label_paytype->setHidden(false);
        ui.label_total->setHidden(false);
        ui.edt_total_fee->setHidden(false);
        ui.combo_pay_type->setHidden(false);
        ui.label_5->setHidden(true);
        ui.label_8->setHidden(true);
        ui.label_7->setHidden(true);
        ui.label_9->setHidden(true);
        ui.combo_order_status->setHidden(true);
        ui.combo_order_type->setHidden(true);
        ui.combo_locker_no->setHidden(true);
        ui.edt_phone->setHidden(true);
        /// 支付记录
        QStringList list8 = {
            tr("Index"),
            tr("Locker No."),
            tr("Fee Paid"),
            tr("Pay Time"),
            tr("Pay Mode"),
            tr("Order ID"),
            tr("Pay Order ID")};
        model_query_->setHorizontalHeaderLabels(list8);
        model_query_->setColumnCount(list8.size());
    }
    model_query_->removeRows(0,model_query_->rowCount());
}

void CBackendWnd::store_data_to_model_dcb(const DoorControlBoard &dcb, const QModelIndex &index)
{
    model_dcb_->setData(index, 1, ROLE_DCB_FLAG);
    model_dcb_->setData(index, dcb.col, ROLE_DCB_COL);
    model_dcb_->setData(index, dcb.count, ROLE_DCB_COUNT);
    model_dcb_->setData(index, dcb.protocol_type, ROLE_DCB_PROTOCOL);
    model_dcb_->setData(index, dcb.datalinkopt.type, ROLE_DCB_TYPE);
    model_dcb_->setData(index, dcb.datalinkopt.is_shared, ROLE_DCB_ISSHARED);
    model_dcb_->setData(index, dcb.datalinkopt.localport, ROLE_DCB_LOCALPORT);
    model_dcb_->setData(index, dcb.datalinkopt.remoteport, ROLE_DCB_REMOTEPORT);
    model_dcb_->setData(index, dcb.datalinkopt.remoteaddr.c_str(), ROLE_DCB_REMOTEADDR);
    model_dcb_->setData(index, dcb.datalinkopt.com.c_str(), ROLE_DCB_COM);
    model_dcb_->setData(index, dcb.datalinkopt.baud_rate, ROLE_DCB_BAUDRATE);
    model_dcb_->setData(index, dcb.datalinkopt.flow_control, ROLE_DCB_FLOW_CONTROL);
    model_dcb_->setData(index, dcb.datalinkopt.parity, ROLE_DCB_PARITY);
    model_dcb_->setData(index, dcb.datalinkopt.stop_bits, ROLE_DCB_STOPBITS);
    model_dcb_->setData(index, dcb.datalinkopt.character_size, ROLE_DCB_CHARACTERSIZE);
    model_dcb_->setData(index, dcb.datalinkopt.timeout_conn, ROLE_DCB_TIMEOUTCONN);
    model_dcb_->setData(index, dcb.datalinkopt.timeout_read, ROLE_DCB_TIMEOUTREAD);
    model_dcb_->setData(index, dcb.datalinkopt.timeout_write, ROLE_DCB_TIMEOUTWRITE);
}

void CBackendWnd::read_data_from_model_dcb(DoorControlBoard &dcb, const QModelIndex &index)
{
     dcb.col = model_dcb_->data(index, ROLE_DCB_COL).toInt();
     dcb.count = model_dcb_->data(index, ROLE_DCB_COUNT).toInt();
     dcb.protocol_type = model_dcb_->data(index, ROLE_DCB_PROTOCOL).toInt();
     dcb.datalinkopt.type = model_dcb_->data(index, ROLE_DCB_TYPE).toInt();
     dcb.datalinkopt.is_shared = model_dcb_->data(index, ROLE_DCB_ISSHARED).toInt();
     dcb.datalinkopt.localport = model_dcb_->data(index, ROLE_DCB_LOCALPORT).toInt();
     dcb.datalinkopt.remoteaddr = model_dcb_->data(index, ROLE_DCB_REMOTEADDR).toString().toStdString();
     dcb.datalinkopt.remoteport = model_dcb_->data(index, ROLE_DCB_REMOTEPORT).toInt();
     dcb.datalinkopt.com = model_dcb_->data(index, ROLE_DCB_COM).toString().toStdString();
     dcb.datalinkopt.baud_rate = model_dcb_->data(index, ROLE_DCB_BAUDRATE).toInt();
     dcb.datalinkopt.flow_control = model_dcb_->data(index, ROLE_DCB_FLOW_CONTROL).toInt();
     dcb.datalinkopt.parity = model_dcb_->data(index, ROLE_DCB_PARITY).toInt();
     dcb.datalinkopt.stop_bits = model_dcb_->data(index, ROLE_DCB_STOPBITS).toInt();
     dcb.datalinkopt.character_size = model_dcb_->data(index, ROLE_DCB_CHARACTERSIZE).toInt();
     dcb.datalinkopt.timeout_conn = model_dcb_->data(index, ROLE_DCB_TIMEOUTCONN).toInt();
     dcb.datalinkopt.timeout_read = model_dcb_->data(index, ROLE_DCB_TIMEOUTREAD).toInt();
     dcb.datalinkopt.timeout_write = model_dcb_->data(index, ROLE_DCB_TIMEOUTWRITE).toInt();
}
